/*
 * TOS-MAC user interface
 * Driver is registered as a character device,
 * so normal system calls(open/close/read/write/ioctl) 
 * are used to recv/trans data and configure radio device.
 */

/**
 * @file tosmac.h
 * @brief Linux radio driver and packet definition.
 */

#ifndef __TOSMAC_H
#define __TOSMAC_H 
#include <linux/types.h>

#define TOSMAC_MAJOR  240
#define TOSMAC_DEVICE "/dev/tosmac"
/*
 * default value of data length in packet
 * 28 is the value IMote2 uses.
 * 116 is the max length can be set
 */
#define TOSH_DATA_LENGTH  28  //!< payload size of packet
/* 
 * Packet structure
 * To be compatible with TinyOS, we provide a packet data structure,
 * which is the definition of packet used in TinyOS.
 * User program need to set up a packet before making system calls 
 */
typedef struct __TOS_Msg
{
	__u8 length;   //!< length of entire frame
	__u8 fcfhi;    //!< Frame Control Field higher byte
	__u8 fcflo;    //!< Frame Control Field lower byte
	__u8 dsn;      //!< sequence number
	__u16 destpan; //!< destPAN
	__u16 addr;    //!< destAddr
	__u8 type;     //!< in TinyOS 2.x, this is low byte of sender address
	__u8 group;    //!< in TinyOS 2.x, this is high byte of sender address
	__s8 data[TOSH_DATA_LENGTH]; //!< payload
	__u8 strength; //!< RSSI
	__u8 lqi;      //!<
	__u8 crc;      //!<
	__u8 ack;      //!<
	__u16 time;    //!<
} TOS_Msg;

/*
 * Important:
 * TOSMAC driver is a non-standard character device.
 * Please read descriptions below for each function for details.  
 */

/*
 * Open device
 * Use open( ) system call
 * Device can be opened in blocking or non-blocking mode
 * flags supported:
 *	O_RDWR  			// read/write in blocking mode
 *	O_RDWR|O_NONBLOCK	// read in non-blocking mode, write in blocking mode  
 */
//int open(TOSMAC_DEVICE *device_path, int flags);

/*
 * Close device
 * Use close() system call
 */
//int close(int fd);

/*
 * Read data
 * Use read( ) system call.
 * Each time, one packet will be returned if there are data received.
 * void *buf: the pointer to a packet.
 * count: the length of payload data user want to receive.
 *        it should always be TOSH_DATA_LENGTH
 * If user gives a count value not equaling with TOSH_DATA_LENGTH, then:
 *   -- if (count > TOSH_DATA_LENGTH) 
 *	then read will return at most TOSH_DATA_LENGTH bytes.
 *   -- if (count < TOSH_DATA_LENGTH) 
 *	then read will return at most count bytes and the remaining bytes 
 *	in the payload (if there has) will be lost.
 * Return Value: 
 *   -- on success, read() will return the length of payload it received.
 *   -- on fail(data copy error), -EFAULT will be returned.
 *   -- in non-blocking read, if data is not ready, -EAGAIN will be returned.
 */
//ssize_t read(int fd, void *buf, size_t count);

/*
 * Write data
 * Use write( ) system call.
 * Each time, one packet will be sent. Do initialization of packet before sending.
 * buf: the pointer to a packet.
 * count: the length of payload needs to be sent.
 *	  it should always be as the same as length field in TOS_Msg. so it can be 
 *	  less than or equal with TOSH_DATA_LENGTH
 * If user gives a count value greater than TOSH_DATA_LENGTH, then:
 *   -- if (count > TOSH_DATA_LENGTH) 
 *	then only the first TOSH_DATA_LENGTH bytes in data[] will be written as payload, 
 *	the remaining bytes will be ignored.
 * return value:
 *    -- on success, write() will return the length of payload just been sent out.	
 *    -- on fail, -EFAULT will be returned.
 */
//ssize_t write(int fd, const void *buf, size_t count);

/*
 * Poll device
 * Use poll() or select() system call to poll device.
 * Note: the device must be opened non-blocking for these to work.
 */
// int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
//            struct timeval *timeout);
// int poll(struct pollfd *ufds, nfds_t nfds, int timeout);

/*
 * Configure device
 * Use ioctl() system call.
 * cmd: the feature needs to be set, such as channel, power
 * arg: the value will be set to that feature if necessary
 */
//int ioctl(int fd, unsigned int cmd, unsigned int arg);

/*IOMAGIC for TOSMAC driver*/
#define TOSMAC_IOCTL_MAGIC   0xF4
/*IOCTL commands*/
/* set local address, it should be unsigned short integer */
#define TOSMAC_IOSETADDR        _IOW(TOSMAC_IOCTL_MAGIC, 0, __u16)
/* get local address */
#define TOSMAC_IOGETADDR        _IO(TOSMAC_IOCTL_MAGIC,  1)
/* enable radio AUTO ACK */
#define TOSMAC_IOAUTOACK        _IO(TOSMAC_IOCTL_MAGIC,  2)
/* disable radio AUTO ACK */
#define TOSMAC_IODISAUTOACK     _IO(TOSMAC_IOCTL_MAGIC,  3)
/* set radio working channel, value should be between 11 and 26 */
#define TOSMAC_IOSETCHAN        _IOW(TOSMAC_IOCTL_MAGIC, 4, __u16)
/* get current radio working channel */
#define TOSMAC_IOGETCHAN        _IO(TOSMAC_IOCTL_MAGIC,  5)
/* set radio working frequency, value should be between 2405 to 2480 */
#define TOSMAC_IOSETFREQ        _IOW(TOSMAC_IOCTL_MAGIC, 6, __u16)
/* get current radio working frequency */
#define TOSMAC_IOGETFREQ        _IO(TOSMAC_IOCTL_MAGIC,  7)
/* set TOSH_DATA_LENGTH value, the max value can be set is 116 */
#define TOSMAC_IOSETMAXDATASIZE _IOW(TOSMAC_IOCTL_MAGIC, 8, __u16)
/* get current value of TOSH_DATA_LENGTH */
#define TOSMAC_IOGETMAXDATASIZE _IO(TOSMAC_IOCTL_MAGIC,  9)
/* set rf power level, value be between 3 to 31*/
#define TOSMAC_IOSETPOWER       _IOW(TOSMAC_IOCTL_MAGIC, 10, __u16)
/* get rf power level */
#define TOSMAC_IOGETPOWER       _IO(TOSMAC_IOCTL_MAGIC,  11)
#endif
